/*
  DigitalReadSerial
 Reads a digital input on pin 2, prints the result to the serial monitor 
 
 This example code is in the public domain.
 */

#define SENSOR_TYPE_BUTTON 1;

#define ACTUATOR_TYPE_RELAY 1;

#define WHEN_OPEN 1;
#define WHEN_CLOSE 2;
//de la direccion 1 a la x
class Sensor {
public:
  int id;
  int type;
  int the_port;
  int state;
  long lastRead;
  long lastReadDown;
};


class Actuator {
public:
  int id;
  int port;
  int secondPort;
  int state;
  int type;
};
class Actuator_persiana {
public:
  int id;
  int portUp;
  int portDown;
  int state;
  int type;
  long init_time;
  int prev_state;
  int time_to_down; 
};


class SensorAction {
public:
  int id_sensor;
  int type;
  int actuate_when; 
  int id_actuator;
  int actuator_mode;


};

int NUM_SENSORS=0;
int NUM_ACTUATORS = 0;
int NUM_ACTUATOR_PERSIANA = 0;
int NUM_ACTIONS = 0;

Sensor sensors[50];
Actuator actuator[50];
Actuator_persiana actuator_persiana[10];
SensorAction actions[100];


bool house_state = true;
int sensorValue =0;
//boolean sensorState[20];
//boolean releState[20] ;
//long lastRead[20];
//long lastReadDown[20];
void setup() {

//SENSORES----------------
    //Dormitorio OK
    addSensor(1,14,1);
    
    //comedor tocando habitaciones (uno de los dos)
    addSensor(2,15,1);
    
    //OK Despacho OK
    addSensor(3,16,1); 
    
    //OK  ( de los 4 el 1o)
    //pasillo
    addSensor(4,17,1);
    
    //OK Pasillo  ( de los 4 el 3o)
    addSensor(5,2,1);
    
    //comedor tocando habitaciones (uno de los dos)
    addSensor(6,9,1);
    
    //Principal de casa...
    addSensor(7,4,1);
    
    //mesita_NOCHE alex
    addSensor(8,3,1);
    
    //Lavavo OK 
    addSensor(9,13,1);
    
    //Invitados mesita de dormir..
    addSensor(10,12,1);
    
    //Comedor  ( de los 4 el 4o)
    addSensor(11,7,1);
    
    //Invitados entrada
    addSensor(12,10,1);
    
    //mesita noche, marc
    addSensor(13,11,1);
    
    //persiana subir comedor
    addSensor(14,18,1);
    //persiana bajar comedor
   addSensor(15,19,1);
    //persiana subir habitacion
    addSensor(16,24,1);
    addSensor(17,23,1);
   // addSensor(17,27,1);
    
    //el  puerto 6 no funciona!!!
    
//ACTUADORES----------------   
    
   //Dormitorio
   addActuator(1,42,0);
   //Dspacho encima mesa
   addActuator(2,43,0);
   //parece que es el distribuidor
   addActuator(3,44,0);
   //Pasillo
   addActuator(4,45,0);
   //Cocina
   addActuator(5,38,0);
   //???
   addActuator(6,39,0);
   //Comedor-Sofa
   addActuator(7,40,0);
   
   //Despacho estanteria
   addActuator(8,41,0);
   //??-- no conectado
   addActuator(9,34,0);
   //????
   addActuator(10,35,0);
   //????
   addActuator(11,36,0);
   //
   addActuator(12,37,0);
   addActuator(13,32,0);
   
   //Comedor tele
   addActuator(14,33,0);
   
   //Lavavo
   addActuator(15,22,0);
   
   //levantar persiana comedor
   addActuator(16,50,0);
   //bajar persiana comedor
   addActuator(17,51,0);
   //luz convidats
   addActuator(18,46,0);
   //Levantar persiana comedor
   addActuator_persiana(1,50,51,12);
   addActuator_persiana(2,48,49,12);
   

   
     
   
   
   
   
   //1 ----> Abrir/apagar luz
   //2 ----> Subir/Bajar persiana
   
  //addAction(2,13);
  // addAction(2,4);
  // addAction(2,7);
   addAction(11,1,3);
   //Despacho..
   addAction(3,1,2);
   addAction(3,1,8);
  
   //Pasillo..
   addAction(5,1,5);
   //Cocina
   addAction(4,1,4);
   addAction(4,1,15);
   //Comedor
   addAction(11,1,7);
   addAction(11,1,14);
   //Dormitorio
   addAction(1,1,1);
   //Lavavo
   addAction(9,1,15);
   //encender luz convidats
   addAction(12,1,18);
   
   //persiana subir
   addAction(14,2,1);
   //persiana bajar
   addAction(15,3,1);
   
   //persiana habitaxion subir..
   addAction(16,2,2);
   //persiana habitacion bajar...
   addAction(17,3,2);
   

  
   
   
  
//HASTA AKI BUENOS...


  //BY DEFAULT
  for (int i =0 ; i < NUM_SENSORS ; i++){
    sensors[i].state =0;
    sensors[i].lastRead =  millis();
    sensors[i].lastReadDown =0;
    pinMode(sensors[i].the_port,INPUT);
  }

  for (int i = 0;i < NUM_ACTUATORS;i++){
    pinMode(actuator[i].port,OUTPUT);
  }
  for (int i = 0;i < NUM_ACTUATOR_PERSIANA;i++){
    pinMode(actuator_persiana[i].portUp,OUTPUT);
    pinMode(actuator_persiana[i].portDown,OUTPUT);
  }
  
  
  Serial.begin(9600);
}

void loop() {

  for ( int a = 0 ; a < NUM_SENSORS; a++){
    int sensor_state;
    sensor_state = digitalRead(sensors[a].the_port);

    if (sensors[a].type == 1 ){ 
      if (sensor_state == HIGH &&  ( millis() - sensors[a].lastRead ) >300){
        Serial.print("Sensor leido ");
         Serial.println(sensors[a].id);
        //Sensor esta activo y hace mas de 300 milis que no se lee...
        if ((millis() - sensors[a].lastReadDown) > 50 ){
          
          //EL SENSOR SE MANTIENE APRETADO MAS DE 50 milis
          sensors[a].lastRead = millis();
          //SE HA APRETADO EL SENSOR!!!

          if (sensors[a].id == 7  ){
            switch_full_house();
          }
           else{
             sensor_button_click(sensors[a].id);
           }
          //HAY QUE VER LAS ACCIONES QUE LE TOCAN HACER
        }
        else{         
         
        }
      }
      else{
         sensors[a].lastReadDown = millis();
      }
    }
  }
  
  readSerial();
  
  check_timmers();
 

}

void readSerial(){
  
   //LEEMOS DEL SERIAL
  int incoming;
  if (Serial.available() > 0) {
    
    // read the incoming byte:
    incoming = Serial.read();
    
    if (incoming == 101){
      int x = readInt();

       
      for (int i = 0 ; i < NUM_ACTUATORS ; i++){
        
        if (  actuator[i].id == x ){
          actuator[i].state = 1; 
          digitalWrite( actuator[i].port, actuator[i].state);
          Serial.print("Activating actuator: ");
          Serial.println(actuator[i].id, DEC);
        }
      }
    }
    else if (incoming == 100){
      int x = readInt();


      for (int i = 0 ; i < NUM_ACTUATORS ; i++){
        if (  actuator[i].id == x ){
          actuator[i].state = 0; 
          digitalWrite( actuator[i].port, actuator[i].state);
          Serial.print("DEActivating actuator: ");
          Serial.println(actuator[i].id, DEC);
        }
      }
    }
    else{
      Serial.print("Reciving incorrect data ");

    }

  }
  
  
  
}

void addSensor(int id, int port, int type){
  sensors[NUM_SENSORS].id = id;
    sensors[NUM_SENSORS].the_port = port;
    sensors[NUM_SENSORS].type = type;
    NUM_SENSORS ++;
}
void addActuator(int id, int port,int type){
   actuator[NUM_ACTUATORS].id = id;
   actuator[NUM_ACTUATORS].port = port;
  actuator[NUM_ACTUATORS].state = 0;
  actuator[NUM_ACTUATORS].type = type;
  NUM_ACTUATORS ++;
  
}
void addActuator_persiana(int id, int port,int port2,int  time_to_down){
   actuator_persiana[NUM_ACTUATOR_PERSIANA].id = id;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].portUp = port;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].portDown = port2;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].state = 0;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].prev_state = 0;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].type = 0;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].init_time = -1;
   actuator_persiana[NUM_ACTUATOR_PERSIANA].time_to_down = time_to_down;
  NUM_ACTUATOR_PERSIANA ++;

}
void addAction(int id_sensor,int action_type, int id_actuator ){
  actions[NUM_ACTIONS].id_sensor = id_sensor; 
  actions[NUM_ACTIONS].id_actuator =id_actuator;
  actions[NUM_ACTIONS].type = action_type;

  
  NUM_ACTIONS++;
}


int readInt (){
  int x;
  while  (Serial.available() <= 0) {

  }
  x =( Serial.read()-48) *10;       

  while  (Serial.available() <= 0) {

  }
  x += Serial.read()-48;



  return x;

}
void  sensor_button_click(int id_sensor){
  Serial.print("Sensor ");
  Serial.println(id_sensor);

  //Leemos el listado de acciones para el evento x

  for (int x=0 ; x< NUM_ACTIONS; x++){
    if (actions[x].id_sensor == id_sensor){

      //Buscamos cual es su actuador....

    if  (actions[x].type == 1){
      switch_actuator(actions[x].id_actuator);
    }
    else  if  (actions[x].type == 2){
       Serial.print("Sensor aciton 2 ");
      switch_actuator_persiana(actions[x].id_actuator,100);
    }
    else  if  (actions[x].type == 3){
       Serial.print("Sensor action 3 ");
      switch_actuator_persiana(actions[x].id_actuator,0);
    }
      


    }
  }
}

void switch_full_house(){

  house_state = ! house_state;
  for (int i = 0; i < NUM_ACTUATORS; i++){
       if ( house_state == false){
          digitalWrite( actuator[i].port, LOW);
          
       }
       else{
         digitalWrite( actuator[i].port, actuator[i].state);
      }
  }
  for (int i = 0; i < NUM_ACTUATOR_PERSIANA; i++){
       if ( house_state == false){
           switch_actuator_persiana( actuator_persiana[i].id, 0);
          
       }
       else{
            switch_actuator_persiana( actuator_persiana[i].id, 100);
  
      }       
  }
}


void check_timmers(){
  
  //timmer for persianas
   for (int x=0 ; x< NUM_ACTUATOR_PERSIANA; x++){
  
      //Buscamos cual es su actuador....
      if (actuator_persiana[x].init_time != -1 ){
			if (actuator_persiana[x].state - actuator_persiana[x].prev_state >0){
			   //estamos subiendo...
                            
			   int time_for_finish = (actuator_persiana[x].time_to_down)*(actuator_persiana[x].state-actuator_persiana[x].prev_state)/100;

			   if ( ((millis()-actuator_persiana[x].init_time )/1000) > time_for_finish ){
					actuator_persiana[x].init_time = -1;
                                        actuator_persiana[x].prev_state =actuator_persiana[x].state;
					Serial.print("Actuator persiana, fin-subiendo... ");
					Serial.println(actuator_persiana[x].id);
					digitalWrite( actuator_persiana[x].portUp, LOW);
              
				}	
			}
			else{
				//bajando
				 int time_for_finish = (actuator_persiana[x].time_to_down)*(actuator_persiana[x].prev_state - actuator_persiana[x].state)/100;
              
			   if ( ((millis()-actuator_persiana[x].init_time )/1000) > time_for_finish ){
					actuator_persiana[x].init_time = -1;
					actuator_persiana[x].prev_state =actuator_persiana[x].state;
					Serial.print("Actuator persiana, fin-bajando... ");
					Serial.println(actuator_persiana[x].id);
					digitalWrite( actuator_persiana[x].portDown, LOW);
              
				}	
			
			}
		}
	}
}



void switch_actuator(int id_actuator){
   for ( int y = 0; y < NUM_ACTUATORS; y++){
       if (actuator[y].id == id_actuator){
          if (actuator[y].state == 0  ){
              actuator[y].state =1;
          }
          else {
            actuator[y].state = 0;
          }
          Serial.print("Actuator ");
          Serial.println(actuator[y].port);
          digitalWrite( actuator[y].port, actuator[y].state);
     }
  }
}
void switch_actuator_persiana(int id_actuator,int state){
 
  Serial.print(id_actuator);
   for ( int y = 0; y < NUM_ACTUATOR_PERSIANA; y++){
       if (actuator_persiana[y].id == id_actuator){
          
			//si no est� en movimiento....
			if (actuator_persiana[y].state != state  && actuator_persiana[y].state == actuator_persiana[y].prev_state ){

				actuator_persiana[y].prev_state = actuator_persiana[y].state;
				actuator_persiana[y].state = state;
				actuator_persiana[y].init_time = millis();
				
				if (actuator_persiana[y].state > actuator_persiana[y].prev_state ){
				//subir persiana
				Serial.print("Actuator persiana, inicio-subiendo... ");
				Serial.println(actuator_persiana[y].id);
				digitalWrite( actuator_persiana[y].portUp, HIGH);
				
				}
				else{
					//subir persiana
					Serial.print("Actuator persiana, inicio-bajando... ");
					Serial.println(actuator_persiana[y].id);
					digitalWrite( actuator_persiana[y].portDown, HIGH);
				}
			}
		else{
			Serial.print("Subirpersiana no funciona porque no ha acabado la accion anterior...");
		 
	        }
            }
	 
	}
}






